#ifndef MATRIX_INC
#define MATRIX_INC

#include "Defines.h"

/*
 * =====================================================================================
 *        Class:  Mat
 *  Description:  Classe que representa uma matriz
 * =====================================================================================
 */
template<class T>
class Mat
{

public:

    /*-----------------------------------------------------------------------------
     *  Contrói uma nova matriz rows x cols
     *-----------------------------------------------------------------------------*/
    Mat(uint _rows, uint _cols = 1) : rows(_rows), cols(_cols),
        data(new T[_rows * _cols]()) { }

    /*-----------------------------------------------------------------------------
     *  Contrói uma nova matriz a partir de outra
     *-----------------------------------------------------------------------------*/
    Mat(const Mat<T> &mat) : rows(mat.rows), cols(mat.cols),
            data(new T[mat.rows * mat.cols]())
    {
        for(uint i = 0; i < size(); i++)
            data[i] = mat.data[i];
    }

    /*-----------------------------------------------------------------------------
     *  Destróia a matriz
     *-----------------------------------------------------------------------------*/
    virtual ~Mat() { delete[] data; }

    /*-----------------------------------------------------------------------------
     *  Retorna uma referência para o valor (i,j) da matriz
     *-----------------------------------------------------------------------------*/
    T& at(uint i, uint j) { return data[i * cols + j]; }

    /*-----------------------------------------------------------------------------
     *  Retorna uma referência para o elemento i da matriz
     *-----------------------------------------------------------------------------*/
    T& at(uint i) { return data[i]; }

    /*-----------------------------------------------------------------------------
     *  Retorna o tamanho = linhas x colunas
     *-----------------------------------------------------------------------------*/
    ulong size() { return rows * cols; }

    /*-----------------------------------------------------------------------------
     *  Linhas
     *-----------------------------------------------------------------------------*/
    uint rows;

    /*-----------------------------------------------------------------------------
     *  Colunas
     *-----------------------------------------------------------------------------*/
    uint cols;

    /*-----------------------------------------------------------------------------
     *  Vetor de valores
     *-----------------------------------------------------------------------------*/
    T* data;

};

/*-----------------------------------------------------------------------------
 *  Matriz de double
 *-----------------------------------------------------------------------------*/
typedef Mat<double> Matrix;

/*-----------------------------------------------------------------------------
 *  Ponteiro para Matriz de double
 *-----------------------------------------------------------------------------*/
typedef shared_ptr<Matrix> MatrixPtr;


#endif
